#pragma once
#include <pthread.h>
#include "Thread.hpp"
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include "LockGuard.hpp"
#include "Task.hpp"

/************************
 *            添加单例模式
 * ******************* */

const int defaultnum = 5;
struct ThreadDate
{

public:
    ThreadDate()
    {
    }
    std::string _threadname;
};

template <class T>
class ThreadPool
{
private:
    ThreadPool(int threadnum = defaultnum)
        : _threadnum(threadnum)
    {
        for (int i = 0; i < threadnum; i++)
        {
            std::string threadname = "thread-" + std::to_string(i + 1);
            ThreadDate date;
            Thread<ThreadDate> t(threadname, std::bind(&ThreadPool::ThreadRountinue, this, std::placeholders::_1), date);
            _threads.emplace_back(t);
        }
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    ThreadPool<T> operator=(const ThreadPool<T> &) = delete;
    ThreadPool(const ThreadPool<T> &) = delete;

public:

    static ThreadPool<T>* GetInstance(){
        if(instance==nullptr)//防止频繁申请锁
        {
            LockGuard lockguard(&sig_lock);
            if(instance==nullptr){
                std::cout<<"获取单例成功!"<<std::endl;
                
                return instance=new ThreadPool<T>();
            }
        }
        return instance;
    }
    bool Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
        }
        return true;
    }

    void Push(T &in)
    {
        LockGuard lockguard(&_mutex);
        _q.push(in);
        std::cout << "push : " << in.PrintTask() << std::endl;
        pthread_cond_signal(&_cond);
    }

    void ThreadRountinue(ThreadDate &date)
    {
        while (true)
        {
            T t;
            {
                LockGuard lockguard(&_mutex);
                while (_q.empty())
                {
                    pthread_cond_wait(&_cond, &_mutex);
                }
                t = _q.front();
                _q.pop();
            }
            // 处理数据
            t();
            std::cout << t.PrintResult() << std::endl;
        }
    }

private:
    int _threadnum;
    std::queue<T> _q;
    std::vector<Thread<ThreadDate>> _threads;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    static pthread_mutex_t sig_lock;
    static ThreadPool<T> *instance;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::instance=nullptr;


//初始化单例锁
template<class T>
pthread_mutex_t ThreadPool<T>::sig_lock=PTHREAD_MUTEX_INITIALIZER;
